﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using AloneLibrary.Services.Camera;
using XNAnimation;

namespace AloneLibrary.GameObjects
{
	public class StaticGameObject : GameObject
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="StaticGameObject"/> class.
		/// </summary>
		/// <param name="model">The model.</param>
		public StaticGameObject(Model model, Effect effect)
			: base(model, effect)
		{
			CreateBoundingBox();
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="StaticGameObject"/> class.
		/// </summary>
		/// <param name="model">The model.</param>
		/// <param name="position">The position.</param>
		/// <param name="direction">The direction.</param>
		/// <param name="scale">The scale.</param>
		public StaticGameObject(Model model, Effect effect, Vector3 position, Vector2 rotation, float scale)
			: base(model, effect, position, rotation, scale)
		{
			CreateBoundingBox();
		}

		/// <summary>
		/// Gets or sets the bounding box.
		/// </summary>
		/// <value>The bounding box.</value>
		public BoundingBox BoundingBox //for the static objects
		{
			get { return boundingBox; }
			set { boundingBox = value; }
		}


		/// <summary>
		/// Draws the specified game time.
		/// </summary>
		/// <param name="gameTime">The game time.</param>
		/// <param name="camera">The camera.</param>
		public override void Draw(GameTime gameTime, ICameraHandler camera)
		{
			Matrix[] transforms = new Matrix[model.Bones.Count];
			model.CopyAbsoluteBoneTransformsTo(transforms);

			world = Matrix.CreateScale(Scale)
			* Matrix.CreateRotationY(Rotation.Y)
			* Matrix.CreateTranslation(Position);

			foreach (ModelMesh modmesh in model.Meshes)
			{
				foreach (BasicEffect effect in modmesh.Effects)
				{
					effect.EnableDefaultLighting();
					effect.PreferPerPixelLighting = true;
					effect.World = world;
					effect.Projection = camera.Projection;
					effect.View = camera.View;
				}
				modmesh.Draw();
			}
			base.Draw(gameTime, camera);
		}


        /// <summary>
        /// Creates the bounding box.
        /// </summary>
		private void CreateBoundingBox()
		{
			boundingBox = new BoundingBox();

			Matrix[] transforms = new Matrix[model.Bones.Count];
			model.CopyAbsoluteBoneTransformsTo(transforms);

			foreach (ModelMesh mesh in model.Meshes)
			{
				VertexPositionColor[] vertices = new VertexPositionColor[mesh.VertexBuffer.SizeInBytes / mesh.MeshParts[0].VertexStride];
				mesh.VertexBuffer.GetData<VertexPositionColor>(vertices);

				Vector3 min = vertices[0].Position;
				Vector3 max = vertices[0].Position;

				for (int i = 1; i < vertices.Length; i++)
				{
					min = Vector3.Min(min, vertices[i].Position);
					max = Vector3.Max(max, vertices[i].Position);
				}

				boundingBox.Min = Vector3.Min(boundingBox.Min, min);
				boundingBox.Max = Vector3.Max(boundingBox.Max, max);
			}

			boundingBox.Max.Y = 10000000f;

			boundingBox.Min = new Vector3(boundingBox.Min.X * Scale, boundingBox.Min.Y * Scale, boundingBox.Min.Z * Scale);
			boundingBox.Max = new Vector3(boundingBox.Max.X * Scale, boundingBox.Max.Y * Scale, boundingBox.Max.Z * Scale);

			boundingBox.Min = new Vector3(boundingBox.Min.X + Position.X, boundingBox.Min.Y + Position.Y, boundingBox.Min.Z + Position.Z);
			boundingBox.Max = new Vector3(boundingBox.Max.X + Position.X, boundingBox.Max.Y, boundingBox.Max.Z + Position.Z);
		}

        /// <summary>
        /// Determines whether [is colliding ray] [the specified ray].
        /// </summary>
        /// <param name="ray">The ray.</param>
        /// <returns>
        /// 	<c>true</c> if [is colliding ray] [the specified ray]; otherwise, <c>false</c>.
        /// </returns>
		public bool isCollidingRay(Ray ray)
		{
			return (ray.Intersects(this.BoundingBox) != null);
		}
	}
}
